import pymarc
from PyQt5.Qt import *
from widget.my_window import MyWindow
import configparser
from widget.info_box import InfoBox, ChoiceBox
from pymarc import MARCReader
import json
from widget.daoru_page.source_init_page.add_marc_init_window import MarcAddOrEdtWindow


class MarcInitPage(MyWindow):
    '''
    sqlserver配置页面（导入页面的子页面）
    '''
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.marc_source_dict = {
            'name': 'marc',
            'uni': {
                'file_path': "",
                'marc_init_sec': "",
            },
            'com': {
                'field_name_list': [],
                'field_content_list': []
            }
        }

        self.setAttribute(Qt.WA_StyledBackground, False)
        # 窗口置顶
        self.setWindowModality(Qt.ApplicationModal)
        # self.setWindowFlag(Qt.WindowStaysOnTopHint)
        # 父窗口实例对象
        self.my_parent_window = kwargs['my_parent']
        # 窗口标题
        self.label_title = QLabel(self)
        self.label_title.resize(230, 40)
        self.label_title.setText('Marc 来源配置')
        self.label_title.move(10, 5)

        self.setup_ui()

    def setup_ui(self):
        # 基础面板位置
        self.base_widget = QWidget(self)
        self.base_widget.setGeometry(0, 50, self.width(), self.height()-50)

        # 第一行 ---------------------------------------------------
        self.choice_marc_label = QLabel(text='选择marc文件：')
        self.choice_marc_label.setFixedWidth(120)
        self.choice_marc_input = QLineEdit()
        self.choice_marc_input.setFixedWidth(300)
        self.choice_marc_button = QPushButton(text='...')
        self.choice_marc_button.setFixedWidth(30)
        self.choice_marc_button.clicked.connect(self.choice_marc_file)
        row0 = QHBoxLayout()
        row0.addWidget(self.choice_marc_label)
        row0.addWidget(self.choice_marc_input)
        row0.addWidget(self.choice_marc_button)
        row0.addStretch(1)  # 站位分割

        # 第二行 ---------------------------------------------------
        self.choice_func_label = QLabel(text='选择导入方案：')
        self.choice_func_label.setFixedWidth(120)
        self.choice_func_combox = QComboBox()
        self.choice_func_combox.setFixedWidth(300)
        self.choice_func_combox.setView(QListView())  # 通过setView和全局qss设置行高
        self.refresh_combox()
        self.choice_func_del_btn = QPushButton(text='删除当前方案')
        self.choice_func_del_btn.clicked.connect(lambda: self.delete_marc_sec(self.choice_func_combox.currentText()))
        self.choice_func_edt_btn = QPushButton(text='编辑当前方案')
        self.choice_func_edt_btn.clicked.connect(lambda: self.show_edt_or_add_window('edt', self.choice_func_combox.currentText()))
        self.choice_func_add_btn = QPushButton(text='新增方案')
        self.choice_func_add_btn.clicked.connect(lambda: self.show_edt_or_add_window('add', self.choice_func_combox.currentText()))

        # self.choice_func_save_btn = QPushButton(text='保存')
        row1 = QHBoxLayout()
        row1.addWidget(self.choice_func_label)
        row1.addWidget(self.choice_func_combox)
        row1.addWidget(self.choice_func_del_btn)
        row1.addWidget(self.choice_func_edt_btn)
        row1.addWidget(self.choice_func_add_btn)
        # row1.addWidget(self.choice_func_save_btn)
        row1.addStretch(1)  # 站位分割

        # 第三行, 初始化表格 ---------------------------------------------------
        self.table1 = QTableWidget()
        self.table1.setFixedWidth(870)
        self.table1.setFixedHeight(370)
        # 设置表格的列数为2列
        self.table1.setColumnCount(6)
        # self.table1.setVerticalHeaderLabels(["第一列", "第二列"])
        # 设置表格每列的宽度
        self.table1.setColumnWidth(0, 130)
        self.table1.setColumnWidth(1, 130)
        self.table1.setColumnWidth(2, 130)
        self.table1.setColumnWidth(3, 130)
        self.table1.setColumnWidth(4, 130)
        self.table1.setColumnWidth(5, 130)
        # self.table1.setColumnWidth(2, 80)
        # print(field_list)
        self.table1.setHorizontalHeaderLabels(["Marc字段", "分隔符1", "分隔符2", "Marc字段", "对应数据库字段名称", "是否导入"])
        # 刷新表格
        self.refresh_table()
        # 表格监听表，如果表选择框改变，那么刷新表格
        self.choice_func_combox.currentTextChanged.connect(self.refresh_table)
        row2 = QHBoxLayout()
        row2.addWidget(self.table1)

        # 最后一行 (底部常规按钮) ---------------------------------------------------
        self.okButton = QPushButton(text='确定')
        self.okButton.clicked.connect(self.field_get)
        self.cancelButton = QPushButton(text="取消")
        self.cancelButton.clicked.connect(self.close_btn.click)
        row_last = QHBoxLayout()
        row_last.addStretch(1)  # 站位分割
        row_last.addWidget(self.okButton)
        row_last.addWidget(self.cancelButton)

        # 行插入列，并调整间隔 ---------------------------------------------------
        vbox = QVBoxLayout()
        vbox.addLayout(row0)
        vbox.addStretch(1)  # 站位分割
        vbox.addLayout(row1)
        vbox.addStretch(1)  # 站位分割
        vbox.addLayout(row2)
        vbox.addStretch(10)  # 站位分割
        vbox.addLayout(row_last)

        self.base_widget.setLayout(vbox)

    def refresh_table(self):
        '''
        刷新表格
        :return:
        '''
        sec = self.choice_func_combox.currentText()

        if not sec:
            return
        cf = self.get_init_file_cf()
        kl = cf.get(sec, "field_list")
        if not kl:
            return
        json_list = json.loads(kl)
        self.table1.setRowCount(len(json_list))
        for i, js_dict in enumerate(json_list):
            self.table1.setItem(i, 0, QTableWidgetItem(js_dict['field']))
            self.table1.setItem(i, 1, QTableWidgetItem(js_dict['indicator1']))
            self.table1.setItem(i, 2, QTableWidgetItem(js_dict['indicator2']))
            self.table1.setItem(i, 3, QTableWidgetItem(js_dict['subfield']))
            self.table1.setItem(i, 4, QTableWidgetItem(js_dict['fieldname']))
            check_box = QCheckBox()
            check_box.setStyleSheet('margin-left: 55px')
            check_box.setChecked(True if js_dict['import'] == 1 else False)
            self.table1.setCellWidget(i, 5, check_box)

    def get_init_file_cf(self):
        cf = configparser.ConfigParser()
        print(qApp.cx_project_root.replace('\\', '/') + '/init_file/init/marcfield.ini')
        cf.read(qApp.cx_project_root.replace('\\', '/') + '/init_file/init/marcfield.ini')
        return cf

    def init_write(self, cf):
        cf.write(open(qApp.cx_project_root.replace('\\', '/') + r'/init_file/init/marcfield.ini', "w"))

    def refresh_combox(self):
        '''
        刷新 marc 字段配置
        :return:
        '''
        # qApp.cx_project_root.replace('\\', '/') + '/init_file/init/marcfield.ini'
        cf = self.get_init_file_cf()
        secs = cf.sections()
        self.choice_func_combox.clear()
        secs_order_list = []
        for sec in secs:
            for i in range(len(secs)):
                order_num = cf.get(sec, "order_num")
                if str(i) == order_num:
                    secs_order_list.append(sec)
                    break
        self.choice_func_combox.addItems(secs_order_list)
        # print(secs)

    def delete_marc_sec(self, sec):
        '''
        删除当前配置
        :return:
        '''
        self.qryscm_box = ChoiceBox('确定要删除当前配置吗')
        def delete_mc():
            cf = self.get_init_file_cf()
            cf.remove_section(sec)
            self.init_write(cf)
            self.refresh_combox()
            self.qryscm_box.close()
        self.qryscm_box.enter_btn.clicked.connect(delete_mc)
        self.qryscm_box.show()


    def choice_marc_file(self):
        '''
        选择 marc 文件路径
        :return:
        '''
        # 打开excl操作 start ---------------------------------------
        # daoru_combo1_key = self.daoru_combo1.currentText()
        # print(daoru_combo1_key)
        file_path = QFileDialog.getOpenFileName(self, "选择文件", "/", "Text Files (*.marc *.iso *.mrc *.cnm *.txt *.mdb);;All Files (*)")
        marc_path = file_path[0]
        print(marc_path)
        # 文件数据保存方法（挂载数据到qApp）
        if not marc_path:
            return
        else:
            # 打开excl比较慢，先给个弹窗，然后完成操作时关掉
            self.excl_tag_box = InfoBox('加载Marc中...')
            self.excl_tag_box.show()
            # todo  加载marc前十条数据， 获取字段名和内容
            self.choice_marc_input.setText(marc_path)
            # 打开excl操作 end ---------------------------------------
            # 关闭提示
        self.excl_tag_box.close()

    def save_marc_init(self):
        '''
        保存 marc配置
        :return:
        '''
        if self.table1.rowCount() == 0:
            return

        marc_init_list = []
        for i in range(self.table1.rowCount()):
            marc_init = {}
            marc_init['field'] = self.table1.item(i, 0).text()
            marc_init['indicator1'] = self.table1.item(i, 1).text()
            marc_init['indicator2'] = self.table1.item(i, 2).text()
            marc_init['subfield'] = self.table1.item(i, 3).text()
            marc_init['fieldname'] = self.table1.item(i, 4).text()
            marc_init['import'] = 1 if self.table1.cellWidget(i, 5).isChecked() else 0
            marc_init_list.append(marc_init)
        marc_init_list_json = json.dumps(marc_init_list, ensure_ascii=False)
        # print(marc_init_list_json)
        sec = self.choice_func_combox.currentText()
        if not sec:
            return
        cf = self.get_init_file_cf()
        cf.set(sec, "field_list", marc_init_list_json)
        self.init_write(cf)
        # print(1111111111111)

    def show_edt_or_add_window(self, opt_name, marc_init_sec):
        '''
        展示编辑或新增页面
        :return:
        '''
        self.marc_init_window = MarcAddOrEdtWindow(width=900, height=550, my_parent=self, opt_name=opt_name, marc_init_sec=marc_init_sec)
        self.marc_init_window.show()

    def field_get(self):
        '''
        获取marc信息挂载到 qApp
        :return:
        '''
        # 没有选择marc文件的话直接返回
        marc_path = self.choice_marc_input.text()
        if not marc_path or self.table1.rowCount() == 0:
            self.wxzwj_box = InfoBox('未选择marc数据 或 marc配置文件')
            self.wxzwj_box.show()
            return

        # 保存配置文件
        self.save_marc_init()

        # 挂载信息到qApp
        # marc_init = self.choice_func_combox.currentText()
        # if not marc_path or marc_init:
        #
        #     return
        self.marc_source_dict['uni']['file_path'] = marc_path
        marc_init_sec = self.choice_func_combox.currentText()
        self.marc_source_dict['uni']['marc_init_sec'] = marc_init_sec

        mc = MarcUtils()
        records = mc.get_marc(marc_path, 10)
        fmt_data = mc.format_records(marc_init_sec, records)
        if not fmt_data:
            return
        self.marc_source_dict['com']['field_name_list'] = fmt_data[0]
        self.marc_source_dict['com']['field_content_list'] = fmt_data[1:]

        # 挂载格式化的数据到qApp
        qApp.cx_src = self.marc_source_dict
        self.my_parent_window.daoru_input1.setText(self.marc_source_dict['uni']['file_path'])
        self.close()

        # print("marc_data: {0}".format(marc_data))

        # print(qApp.cx_src)
        # print(1/0)
        # mc.get_marc(qApp.cx_src)

    def keyPressEvent(self, QKeyEvent):  # 键盘某个键被按下时调用
        '''
        按下 ESC关闭当前页
        :param QKeyEvent:
        :return:
        '''
        # 参数1  控件
        if QKeyEvent.key() == Qt.Key_Escape:  # 判断是否按下了ESC键
            self.close_btn.click()

    # class ExclInitFunc(object):
#     '''
#     将marc中的数据挂载到qApp上
#     '''
#     def __init__(self, marc_path):
#         # excl文件路径
#         self.marc_path = marc_path
#         # excl文件中的数据
#         self.excl_source_dict = {
#             'name': 'marc',
#             'uni': {
#                 'file_path': marc_path,
#             },
#             'com': {
#                 'field_name_list': [],
#                 'field_content_list': []
#             }
#         }
#
#     def marc2qApp(self):
#         '''
#         读取excl中的数据
#         :return:
#         '''
#         # 打开 marc
#         MarcUtils.get_marc(self.marc_path, 10)
#         # TODO
#
#
#         # sheet1_object = workbook.sheet_by_index(0)
#         # 获取第一列数据
#         # for i in range(10):
#         #
#         #     col_slice = sheet1_object.row_values(rowx=i)
#         #     if i == 0:
#         #         self.excl_source_dict['com']['field_name_list'] = col_slice
#         #     else:
#         #         self.excl_source_dict['com']['field_content_list'].append(col_slice)
#         # print(self.excl_source_dict)
#         # # excl表的前十条数据挂载到qApp中
#         # qApp.cx_src = self.excl_source_dict
#
#


class MarcUtils(object):
    '''
    marc数据操作类
    '''
    @classmethod
    def get_marc(self, fpath, num=None):
        '''
        读取 marc
        :param fpath:
        :param num:
        :return:
        '''
        # ma = MarcUtils()
        # fpath = r'D:\marc20171218.iso'
        # ma.daorumarc(fpath)

        # with open(fpath, 'rb') as fh:
        #     reader = MARCReader(fh)
        #     for record in reader:
        #         print(record.as_json(indent=2))

        count = 0
        headings = set()
        headings.add('LDR')
        records = []
        # with open(fpath, 'rb') as marc_file:
        #    utf8_handling = 'replace' if force_utf8 else 'strict'
        #    file_encoding="UTF-8"
        #    reader = MARCReader(marc_file)
        print(fpath)
        reader = MARCReader(open(fpath, 'rb'), file_encoding="utf-8", utf8_handling='replace')

        # print('sum(1 for _ in reader): {0}'.format(sum(1 for _ in reader)))
        # print(list(reader))
        # for i, red in reader:
        #     print(i, red)
        # print(1/0)
        for record in reader:
            if record == "eof":
                break
            try:
                rec_dict = {'LDR': record.leader}
                rheadings = []
                for field in record.fields:
                    heading = field.tag
                    rheadings.append(heading)

                    if field.is_control_field():
                        rec_dict[heading] = field.value()
                        headings.add(heading)

                    if hasattr(field, 'subfields'):
                        i1 = field.indicator1.replace(' ', '\\')
                        i2 = field.indicator1.replace(' ', '\\')
                        heading = '{0} {1}{2}'.format(heading, i1, i2)

                        # Split subfields
                        c = [code for code in field.subfields[::2]]
                        v = [value for value in field.subfields[1::2]]
                        subfields = [(c[i], v[i]) for i in range(len(c))]
                        for s in subfields:
                            subheading = '{0} ${1}'.format(heading, s[0])
                            n = rheadings.count(field.tag)
                            if n > 1:
                                subheading = '{0} [{1}]'.format(subheading, n)
                            rec_dict[subheading] = s[1]
                            headings.add(subheading)

                records.append(rec_dict)

                if num and count >= num-1:
                    break
            except Exception as ex:
                print("error_num: {0}".format(count))
                print("error_reson: {0}".format(ex))

            count = count + 1
            # print('正在读取marc: {0}'.format(count))

        # print("readover")
        # print(records)
        # data = [headings] + [[r.get(h, '') for h in headings] for r in records]
        # print(data)
        # print(ecords)

        return records

    @classmethod
    def format_records(self, marc_init_sec, records):
        row1 = []
        cf = self.get_init_file_cf()
        # secs = cf.sections()
        # print(secs)
        field_list_str = cf.get(marc_init_sec, "field_list")
        # with open('d:\marcfieldtest.json', 'r', encoding='UTF-8') as load_ini:
        # load_field = json.load(kl)
        field_list = json.loads(field_list_str)
        # print(field_list)
        # print(type(field_list))
        # print(1/0)
        for rows in field_list:
            chekyes = rows["import"]
            if chekyes != 0:
                row1.append("{0} {1} {2} {3}   ({4})".format(rows["field"], rows["indicator1"] if rows["indicator1"] else '\\', rows["indicator2"] if rows["indicator2"] else '\\', rows["subfield"], rows['fieldname']))
        dictview = [row1]
        fmt_count = 0
        for r in records:
            rowls = []
            find = False
            for h in row1:
                for f in r:
                    # if f[0:3] == h[0:3] and f[len(f) - 2:] == h[len(h) - 2:]:
                    if f[0:3] == h.split(' ')[0] and f[len(f) - 2:] == h.split(' ')[3]:
                        rowls.append(r.get(f))
                        find = True
                        break
                if find == False: rowls.append("")
                find = False
            dictview.append(rowls)
            fmt_count += 1
            # print('正在格式化marc: {0}'.format(fmt_count))
        return dictview

    @classmethod
    def get_init_file_cf(self):
        cf = configparser.ConfigParser()
        print(qApp.cx_project_root.replace('\\', '/') + '/init_file/init/marcfield.ini')
        cf.read(qApp.cx_project_root.replace('\\', '/') + '/init_file/init/marcfield.ini')
        return cf

    @classmethod
    def init_write(self, cf):
        cf.write(open(qApp.cx_project_root.replace('\\', '/') + r'/init_file/init/marcfield.ini', "w"))


if __name__ == '__main__':
    fpath = r'C:\Users\cxstar\Desktop\marc20171218.iso'
    records = MarcUtils.get_marc(fpath, 10)

    for rec in records:
        for k in rec:
            print(rec[k])
